#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
#include <cctype>

#include "Controller.h"
#include "Log.h"

PNE_NAMESPACE_BEGIN
// two helper for str utils
// trim space char from start(construct new string)
inline std::string lefttrim(const std::string &str)
{
    std::string s(str);
    // 去除空白字符方法
    s.erase(s.begin(),
            std::find_if_not<decltype(s.begin()), int(int)>(s.begin(), s.end(), std::isspace));

    return s;
}

inline std::string righttrim(const std::string &str)
{
    std::string s(str);
    // 从右边界开始切分
    s.erase(std::find_if_not<decltype(s.rbegin()), int(int)>(s.rbegin(), s.rend(), std::isspace).base(), s.end());

    return s;
}
// end two helper

void ParseControllerConf(std::string filepath,
                         std::vector<sf::Keyboard::Key> &p1,
                         std::vector<sf::Keyboard::Key> &p2)
{
    // 游戏手柄键类
    const std::string buttonStrings[] = {"A",
                                         "B",
                                         "Select",
                                         "Start",
                                         "Up",
                                         "Down",
                                         "Left",
                                         "Right"};

    // 真实电脑键类
    const std::string keys[] = {"A",
                                "B",
                                "C",
                                "D",
                                "E",
                                "F",
                                "G",
                                "H",
                                "I",
                                "J",
                                "K",
                                "L",
                                "M",
                                "N",
                                "O",
                                "P",
                                "Q",
                                "R",
                                "S",
                                "T",
                                "U",
                                "V",
                                "W",
                                "X",
                                "Y",
                                "Z",
                                "Num0",
                                "Num1",
                                "Num2",
                                "Num3",
                                "Num4",
                                "Num5",
                                "Num6",
                                "Num7",
                                "Num8",
                                "Num9",
                                "Escape",
                                "LControl",
                                "LShift",
                                "LAlt",
                                "LSystem",
                                "RControl",
                                "RShift",
                                "RAlt",
                                "RSystem",
                                "Menu",
                                "LBracket",
                                "RBracket",
                                "SemiColon",
                                "Comma",
                                "Period",
                                "Quote",
                                "Slash",
                                "BackSlash",
                                "Tilde",
                                "Equal",
                                "Dash",
                                "Space",
                                "Return",
                                "BackSpace",
                                "Tab",
                                "PageUp",
                                "PageDown",
                                "End",
                                "Home",
                                "Insert",
                                "Delete",
                                "Add",
                                "Subtract",
                                "Multiply",
                                "Divide",
                                "Left",
                                "Right",
                                "Up",
                                "Down",
                                "Numpad0",
                                "Numpad1",
                                "Numpad2",
                                "Numpad3",
                                "Numpad4",
                                "Numpad5",
                                "Numpad6",
                                "Numpad7",
                                "Numpad8",
                                "Numpad9",
                                "F1",
                                "F2",
                                "F3",
                                "F4",
                                "F5",
                                "F6",
                                "F7",
                                "F8",
                                "F9",
                                "F10",
                                "F11",
                                "F12",
                                "F13",
                                "F14",
                                "F15",
                                "Pause"};

    std::ifstream file(filepath);
    std::string line;
    enum class PlayerState
    {
        Player1,
        Player2,
        None
    } state;

    unsigned int line_no = 0;

    while (std::getline(file, line))
    {
        line = righttrim(lefttrim(line));   // 全空白字符去除
        if (line[0] == '#' || line.empty()) // 以#开头或者一行为空
            continue;
        else if (line == "[Player1]") // 解释
            state = PlayerState::Player1;
        else if (line == "[Player2]")
            state = PlayerState::Player2;
        else if (state == PlayerState::Player1 || state == PlayerState::Player2)
        {
            auto divider = line.find("="); // 以=为界对配置项做切分
            // 左边项iterator
            auto it =
                std::find(std::begin(buttonStrings), std::end(buttonStrings), lefttrim(righttrim(line.substr(0, divider))));
            // 右边项iterator
            auto it2 =
                std::find(std::begin(keys), std::end(keys), lefttrim(righttrim(line.substr(divider + 1))));

            if (it == std::end(buttonStrings) || it2 == std::end(keys))
            {
                LOG(Level::Error) << "Invalid key in keybind.conf at line number" << line_no << std::endl;
                continue;
            }

            auto i = std::distance(std::begin(buttonStrings), it);
            auto key = std::distance(std::begin(keys), it2);
            // 转译成SFML
            (state == PlayerState::Player1 ? p1 : p2)[i] = static_cast<sf::Keyboard::Key>(key);
        }
        else
            LOG(Level::Error) << "Invalid line in keybind.conf at line number: " << line_no << std::endl;

        ++line_no;
    }
}

PNE_NAMESPACE_END

// DONE